// -*- coding: utf-8 -*- 
/**
 * Project: AlgorithmsLearn
 *
 * @author: yanking
 * Create time: 2022-03-13 16:15
 * IDE: IntelliJ IDEA
 * Introduction:
 */
package com.LeetCodeT.DateTrain;

import org.junit.jupiter.api.Test;

import java.text.DecimalFormat;

public class ValidUtf8 {
    /**
     * 判断整形数组是否是有效的utf-8编码
     *
     * @param data 整形数组
     * @return 有效：true 无效：false
     */
    public boolean validUtf8T(int[] data) {
        // 1 将数据数组转化为二进制 2 判断二进制数组，判断是否符合utf-8编码形式
        String[] binary = transToBinary(data);
        return isUtf8(binary);
    }

    /**
     * 判断给定的字符串数组是否符合utf-8编码
     *
     * @param binary: 给定字符串编码
     */
    private boolean isUtf8(String[] binary) {
        /*
            判断当前二进制字符串前面1的个数，1的个数代表了当前编码的位数，-> 编码的位数决定了后面几个二进制数据字符串的前面编码
            utf-8 编码只有4个字节的编码
         */
        int len = binary.length;
        boolean flag = false;
        for (int i = 0; i < len; i++) {
            flag = false;
            String s = binary[i];
            int n = 0;
            int k = 0;
            while (k < 8 && s.charAt(k++) == '1') {
                ++n;
            }
            if (n == 0) {
                flag = isO(s);
            } else if (n == 2 && len > 1) {
                flag = isT(i + 1, i + 2, binary);
                i++;
            } else if (n == 3) {
                flag = isT(i + 1, i + 3, binary);
                i += 2;
            } else if (n == 4) {
                flag = isT(i + 1, i + 4, binary);
                i += 3;
            }
            if (!flag) {
                return false;
            }
        }
        return flag;
    }

    private boolean isT(int start, int end, String[] binary) {
        for (int i = start; i < end; i++) {
            if (i >= binary.length) {
                return false;
            }
            String s = binary[i];
            if (s.charAt(0) != '1' || s.charAt(1) != '0') {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断字符串是否是一自己编码
     */
    private boolean isO(String s) {
        return s.charAt(0) == '0';
    }

    /**
     * 将整形数组转化为二进制字符串数组进行存储
     */
    private String[] transToBinary(int[] data) {
        DecimalFormat df = new DecimalFormat("00000000");
        int n = data.length;
        String[] binary = new String[n];
        for (int i = 0; i < n; i++) {
            binary[i] = df.format(Integer.valueOf(Integer.toBinaryString(data[i])));
        }
        return binary;
    }


    public boolean validUtf8(int[] data) {
        int n = data.length;
        for (int i = 0; i < n; ) {
            int t = data[i], j = 7;
            while (j >= 0 && (((t >> j) & 1) == 1)) {
                // 计算当前数值前面1的个数
                j--;
            }
            // 当前的字节数
            int cnt = 7 - j;
            if (cnt == 1 || cnt > 4) {
                return false;
            }
            if (i + cnt - 1 >= n) {
                return false;
            }
            for (int k = i + 1; k < i + cnt; k++) {
                if ((((data[k] >> 7) & 1) == 1) && (((data[k] >> 6) & 1) == 0)) {
                    continue;
                }
                return false;
            }
            if (cnt == 0) {
                i++;
            } else {
                i += cnt;
            }
        }
        return true;
    }


    @Test
    public void shout() {
        // int[] ints = {197, 130, 1};
        //int[] ints = {235, 140, 4};
        //int[] ints = {237};
        int[] ints = {240, 162, 138, 147, 145};
        System.out.println(validUtf8(ints));
    }
}
